package com.zzy.chapter2.service;

import com.zzy.chapter2.pojo.AbstractProductItem;
import com.zzy.chapter2.pojo.ProductItem;
import com.zzy.chapter2.pojo.ProductItemComposite;
import com.zzy.chapter2.repo.ProductItemRepository;
import com.zzy.chapter2.utils.RedisCommonProcessor;
import com.zzy.chapter2.visitor.AddItemVisitor;
import com.zzy.chapter2.visitor.DelItemVisitor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Transactional(rollbackOn = Exception.class)
public class ProductItemService {

    @Autowired
    private ProductItemRepository productItemRepository;

    @Autowired
    private RedisCommonProcessor redisCommonProcessor;

    @Autowired
    private AddItemVisitor addItemVisitor;

    @Autowired
    private DelItemVisitor delItemVisitor;

    public ProductItemComposite fetchAllProductItem() {
        // 1. 查询redis缓存
        Object productItem = redisCommonProcessor.get("productItem");
        if (productItem != null) {
            return (ProductItemComposite) productItem;
        }
        // 2. 查询DB
        List<ProductItem> fetchDBItems = productItemRepository.findAll();
        // 3. 封装结果
        ProductItemComposite item = generateProductItemTree(fetchDBItems);
        if (item == null) {
            throw new RuntimeException("没有数据");
        }
        redisCommonProcessor.set("productItem", item);
        return item;
    }

    private ProductItemComposite generateProductItemTree(List<ProductItem> fetchDBItems) {
        List<ProductItemComposite> composites = new ArrayList<>(fetchDBItems.size());
        fetchDBItems.forEach(item -> composites.add(ProductItemComposite.builder()
                .id(item.getId())
                .name(item.getName())
                .pid(item.getPid())
                .build()));
        Map<Integer, List<ProductItemComposite>> groupingList = composites.stream().collect(Collectors.groupingBy(ProductItemComposite::getPid));
        composites.forEach(item -> {
            List<ProductItemComposite> list = groupingList.get(item.getId());
            item.setChild(list == null ? new ArrayList<>() : list.stream().map(x -> (AbstractProductItem) x).collect(Collectors.toList()));
        });
        return composites.isEmpty() ? null : composites.get(0);
    }

    public ProductItemComposite addProductItem(ProductItem productItem) {
        // 1. 更新数据库
        productItemRepository.addItem(productItem.getName(), productItem.getPid());
        // 2. 通过访问者模式先访问数据
        ProductItem targetItem = productItemRepository.findByNameAndPid(productItem.getName(), productItem.getPid());
        ProductItemComposite itemComposite = ProductItemComposite.builder()
                .id(targetItem.getId())
                .pid(targetItem.getPid())
                .name(targetItem.getName())
                .build();
        // 3. 更新緩存
        AbstractProductItem productItemInRedis = addItemVisitor.visit(itemComposite);
        redisCommonProcessor.set("productItem", productItemInRedis);
        return (ProductItemComposite) productItemInRedis;
    }

    public ProductItemComposite delProductItem(ProductItem productItem) {
        // 1. 更新数据库
        productItemRepository.delItem(productItem.getId());
        // 2. 通过访问者模式先访问数据
        ProductItemComposite itemComposite = ProductItemComposite.builder()
                .id(productItem.getId())
                .pid(productItem.getPid())
                .build();
        // 3. 更新緩存
        AbstractProductItem productItemInRedis = delItemVisitor.visit(itemComposite);
        redisCommonProcessor.set("productItem", productItemInRedis);
        return (ProductItemComposite) productItemInRedis;
    }
}
